package fr.inria.arles.temperatureManagement.RFID;

import fr.inria.arles.temperatureManagement.communication.TemperatureManagerCommunicator;
import fr.inria.arles.temperatureManagement.communication.QueryProcessorCommunicator;
import fr.inria.arles.temperatureManagement.exceptions.TimeoutException;
import fr.inria.arles.temperatureManagement.exceptions.QueryException;
import fr.inria.arles.temperatureManagement.exceptions.TemperatureManagerException;
import java.util.HashMap;
import java.util.Map;

import java.util.Collection;
import org.cybergarage.upnp.ControlPoint;
import org.cybergarage.upnp.Device;
import static fr.inria.arles.temperatureManagement.Constants.*;
import static fr.inria.arles.temperatureManagement.utility.DeviceFinder.*;

/**
 * Maintains average of the temperature settings of the users present inside a
 * partition.
 * @author ajay chhatwal
 */
public class RFIDProcessor {

    private Device queryProcessor;
    private Device tempManager;

    /*
     * Constructor to obtain the necessary UPnP Devices required to manage the
     * Temperature of the partition
     */
    public RFIDProcessor() {
        try {
            ControlPoint cp = new ControlPoint();
            cp.start();
            queryProcessor = searchForDevice(cp, QUERY_PROCESSOR_DEVICE);
            tempManager = searchForDevice(cp, TEMPERATURE_MANAGER_DEVICE);
        } catch (TimeoutException ex) {
            ex.printStackTrace();
            System.exit(1);
        }
    }

    private void actuate(String partition, Collection<Double> values)
            throws TemperatureManagerException {
        Double avg = 0.0;
        if (values.size() == 0) {
            avg = DEFAULT_TEMP_SETTING;
        } else {
            for (Double x : values) {
                avg += x;
            }
            avg /= values.size();
        }

        TemperatureManagerCommunicator.setTemp(tempManager,
                partition, avg + "");
        System.out.println("Temperature Setting Updated To:" + avg);
    }
    private Map<String, HashMap<String, Double>> settings =
            new HashMap<String, HashMap<String, Double>>();

    /**
     * Proceses the detection of a new RFID swipe.
     * partition.
     * @param RFID The RFID of the user
     * @param partition The partition in which the RFID was swiped.
     * @throws QueryException
     *              if there is an error in performing the desired action at the
     *              Query Processor Device
     * @throws TemperatureManagerException
     *              if there is an error in performing the desired action at the
     *              Temperature Manager Device
     */
    void processRFID(String RFID, String partition)
            throws QueryException, TemperatureManagerException {

        Double temp;
        HashMap<String, Double> currentPartitonSettings = settings.get(partition);
        if (currentPartitonSettings == null) {
            currentPartitonSettings = new HashMap<String, Double>();
            settings.put(partition, currentPartitonSettings);
        }
        if ((temp = currentPartitonSettings.get(RFID)) != null) {
            currentPartitonSettings.remove(RFID);
            System.out.println("User with RFID tag " + RFID
                    + " and Temperature Setting:" + temp + " has EXITED");
            actuate(partition, currentPartitonSettings.values());
        } else {

            String[] res = QueryProcessorCommunicator.processRFID(queryProcessor, RFID, partition);
            if (res[0].equals("-1")) {
                System.out.println("Authentication Error.");
            } else {
                temp = Double.valueOf(res[1]);
                System.out.println("User with RFID tag " + RFID
                        + " and Temperature Setting:" + temp + " has ENTERED");
                currentPartitonSettings.put(RFID, temp);
                actuate(partition, currentPartitonSettings.values());
            }
        }
    }
}
